Vue 3 + TypeScript 教程

1. Vue.js 简介和特性

Vue.js 是一个渐进式 JavaScript 框架,用于构建用户界面。Vue 3 是 Vue.js 的最新版本,带来了许多新特性和性能改进。Vue 3 的核心特性包括:

  • 响应式系统:Vue 3 使用 Proxy 对象来实现更高效的响应式系统。
  • Composition API:提供了一种新的组织代码的方式,使得逻辑复用和代码组织更加灵活。
  • 更好的 TypeScript 支持:Vue 3 对 TypeScript 的支持更加完善,使得类型检查更加严格和准确。

2. 开发环境搭建

2.1 Vue CLI

Vue CLI 是一个官方提供的脚手架工具,可以帮助你快速搭建 Vue 项目。

npm install -g @vue/cli
vue create my-vue-app

2.2 Vite

Vite 是一个新的前端构建工具,由 Vue 的作者尤雨溪开发。它提供了极快的冷启动和热更新。

npm init vite@latest my-vite-app --template vue-ts

3. 创建第一个 Vue 应用

3.1 使用 Vue CLI 创建项目

vue create my-first-app
cd my-first-app
npm run serve

3.2 使用 Vite 创建项目

npm init vite@latest my-first-app --template vue-ts
cd my-first-app
npm install
npm run dev

4. Vue 实例和生命周期

4.1 Vue 实例

Vue 实例是 Vue 应用的入口点。每个 Vue 应用都从一个 Vue 实例开始。

import { createApp } from 'vue';
import App from './App.vue';

const app = createApp(App);
app.mount('#app');

4.2 生命周期钩子

Vue 实例有一系列的生命周期钩子,允许你在特定阶段执行代码。

export default {
  data() {
    return {
      message: 'Hello Vue 3'
    };
  },
  beforeCreate() {
    console.log('beforeCreate');
  },
  created() {
    console.log('created');
  },
  beforeMount() {
    console.log('beforeMount');
  },
  mounted() {
    console.log('mounted');
  }
};

5. 模板语法和数据绑定

5.1 插值

使用双大括号 {{ }} 进行文本插值。

<template>
  <div>{{ message }}</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      message: 'Hello Vue 3'
    };
  }
});
</script>

5.2 指令

Vue 提供了许多内置指令,如 v-bind、v-if、v-for 等。

<template>
  <div v-if="show">This is visible</div>
  <div v-else>This is hidden</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      show: true
    };
  }
});
</script>

6. 组件化开发

6.1 创建组件

组件是 Vue 应用的基本构建块。你可以创建一个简单的组件并将其导入到主应用中。

// MyComponent.vue
<template>
  <div>My Component</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  name: 'MyComponent'
});
</script>

6.2 使用组件

// App.vue
<template>
  <MyComponent />
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import MyComponent from './MyComponent.vue';

export default defineComponent({
  components: {
    MyComponent
  }
});
</script>

7. 组件通信

7.1 Props

Props 是父组件向子组件传递数据的方式。

// ParentComponent.vue
<template>
  <ChildComponent :message="parentMessage" />
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import ChildComponent from './ChildComponent.vue';

export default defineComponent({
  components: {
    ChildComponent
  },
  data() {
    return {
      parentMessage: 'Hello from parent'
    };
  }
});
</script>
// ChildComponent.vue
<template>
  <div>{{ message }}</div>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue';

export default defineComponent({
  props: {
    message: {
      type: String as PropType<string>,
      required: true
    }
  }
});
</script>

7.2 Events

子组件可以通过 $emit 向父组件发送事件。

// ChildComponent.vue
<template>
  <button @click="sendMessage">Send Message</button>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  methods: {
    sendMessage() {
      this.$emit('message-sent', 'Hello from child');
    }
  }
});
</script>
// ParentComponent.vue
<template>
  <ChildComponent @message-sent="handleMessage" />
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import ChildComponent from './ChildComponent.vue';

export default defineComponent({
  components: {
    ChildComponent
  },
  methods: {
    handleMessage(message: string) {
      console.log(message);
    }
  }
});
</script>

8. 计算属性和侦听器

8.1 计算属性

计算属性是基于依赖进行缓存的属性。

<template>
  <div>{{ fullName }}</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      firstName: 'John',
      lastName: 'Doe'
    };
  },
  computed: {
    fullName(): string {
      return `${this.firstName} ${this.lastName}`;
    }
  }
});
</script>

8.2 侦听器

侦听器用于观察和响应数据的变化。

<template>
  <div>{{ message }}</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      message: 'Hello Vue 3'
    };
  },
  watch: {
    message(newVal: string, oldVal: string) {
      console.log(`Message changed from ${oldVal} to ${newVal}`);
    }
  }
});
</script>

9. 条件渲染和列表渲染

9.1 条件渲染

使用 v-if、v-else 和 v-show 进行条件渲染。

<template>
  <div v-if="show">This is visible</div>
  <div v-else>This is hidden</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      show: true
    };
  }
});
</script>

9.2 列表渲染

使用 v-for 进行列表渲染。

<template>
  <ul>
    <li v-for="item in items" :key="item.id">{{ item.name }}</li>
  </ul>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      items: [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' },
        { id: 3, name: 'Item 3' }
      ]
    };
  }
});
</script>

10. 表单输入绑定

10.1 单向绑定

使用 v-model 进行双向数据绑定。

<template>
  <input v-model="message" />
  <div>{{ message }}</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      message: 'Hello Vue 3'
    };
  }
});
</script>

10.2 多选和单选

<template>
  <input type="checkbox" v-model="checked" />
  <div>{{ checked }}</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      checked: false
    };
  }
});
</script>

11. 单文件组件 (.vue 文件)

单文件组件是 Vue 的核心特性之一,允许你将模板、脚本和样式封装在一个文件中。

<template>
  <div class="example">{{ message }}</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      message: 'Hello Vue 3'
    };
  }
});
</script>

<style scoped>
.example {
  color: red;
}
</style>

12. 组件注册 (全局和局部)

12.1 全局注册

全局注册的组件可以在应用的任何地方使用。

import { createApp } from 'vue';
import App from './App.vue';
import MyComponent from './MyComponent.vue';

const app = createApp(App);
app.component('MyComponent', MyComponent);
app.mount('#app');

12.2 局部注册

局部注册的组件只能在注册的组件中使用。

<template>
  <MyComponent />
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import MyComponent from './MyComponent.vue';

export default defineComponent({
  components: {
    MyComponent
  }
});
</script>

13. Scoped CSS

Scoped CSS 允许你为单文件组件中的样式设置作用域,避免样式冲突。

<template>
  <div class="example">{{ message }}</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      message: 'Hello Vue 3'
    };
  }
});
</script>

<style scoped>
.example {
  color: red;
}
</style>

14. CSS 预处理器 (Sass, Less)

Vue 支持使用 Sass 和 Less 等 CSS 预处理器。

14.1 使用 Sass

<template>
  <div class="example">{{ message }}</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      message: 'Hello Vue 3'
    };
  }
});
</script>

<style lang="scss" scoped>
$primary-color: red;

.example {
  color: $primary-color;
}
</style>

14.2 使用 Less

<template>
  <div class="example">{{ message }}</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      message: 'Hello Vue 3'
    };
  }
});
</script>

<style lang="less" scoped>
@primary-color: red;

.example {
  color: @primary-color;
}
</style>

15. 动态样式和类绑定

15.1 动态类绑定

使用 :class 进行动态类绑定。

<template>
  <div :class="{ active: isActive }">{{ message }}</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      message: 'Hello Vue 3',
      isActive: true
    };
  }
});
</script>

<style scoped>
.active {
  color: red;
}
</style>

15.2 动态样式绑定

使用 :style 进行动态样式绑定。

<template>
  <div :style="{ color: textColor }">{{ message }}</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      message: 'Hello Vue 3',
      textColor: 'red'
    };
  }
});
</script>

16. Vue Router

Vue Router 是 Vue.js 的官方路由管理器。

16.1 安装 Vue Router

npm install vue-router@next

16.2 配置路由

import { createRouter, createWebHistory } from 'vue-router';
import Home from './views/Home.vue';
import About from './views/About.vue';

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;

16.3 使用路由

import { createApp } from 'vue';
import App from './App.vue';
import router from './router';

const app = createApp(App);
app.use(router);
app.mount('#app');

17. Vuex 状态管理

Vuex 是 Vue.js 的官方状态管理库。

17.1 安装 Vuex

npm install vuex@next

17.2 配置 Vuex

import { createStore } from 'vuex';

const store = createStore({
  state() {
    return {
      count: 0
    };
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  }
});

export default store;

17.3 使用 Vuex

import { createApp } from 'vue';
import App from './App.vue';
import store from './store';

const app = createApp(App);
app.use(store);
app.mount('#app');

18. 混入 (Mixins)

混入是一种代码复用机制,允许你将组件的选项混入到其他组件中。

// myMixin.ts
export default {
  data() {
    return {
      message: 'Hello from mixin'
    };
  },
  methods: {
    greet() {
      console.log(this.message);
    }
  }
};
// MyComponent.vue
<template>
  <button @click="greet">Greet</button>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import myMixin from './myMixin';

export default defineComponent({
  mixins: [myMixin]
});
</script>